﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using magic8ballUtility.Sintaksa;

namespace GeneratorSintaksnogAnalizatora
{
    class Program
    {
        static void Main(string[] args)
        {

            if (args.Length < 1 || !File.Exists(args[0]))
            {
                Console.WriteLine("Neispravni argumenti");
                Console.ReadLine();
                return;
            }

            UlaznaSintaksa ulaz = new UlaznaSintaksa(args[0]);

            Generator generator = new Generator(ulaz);

            generator.Pokreni();

            Definicija definicija = new Definicija(generator.gramatika, generator.tablicaAkcija, generator.tablicaNovoStanje);

            using (Stream stream = File.Open(@"definicija.bin", FileMode.Create))
            {
                BinaryFormatter formater = new BinaryFormatter();
                formater.Serialize(stream, definicija);
            }

            //Console.ReadLine();
        }
    }

    //[Serializable]
    //public class Produkcija
    //{
    //    public string Glava { get; set; }
    //    public string Tijelo { get; set; }

    //    public Produkcija(string glava, string tijelo)
    //    {
    //        this.Glava = glava;
    //        this.Tijelo = tijelo;
    //    }

    //    public override string ToString()
    //    {
    //        return this.Glava + " -> " + this.Tijelo;
    //    }

    //}

    public class Stavka
    {
        public int RbrProdukcije { get; set; }
        public int PozicijaTocke { get; set; }
        public string Lookahead { get; set; }
        public bool ReprezentSkupa { get; set; }

        public Stavka(int rbrProdukcije, int pozicijaTocke, string lookahead)
        {
            this.RbrProdukcije = rbrProdukcije;
            this.PozicijaTocke = pozicijaTocke;
            this.Lookahead = lookahead;
            this.ReprezentSkupa = false;
        }

        public Stavka()
        {
            // TODO: Complete member initialization
        }

        public override bool Equals(object obj)
        {
            var objekt = obj as Stavka;
            if (objekt == null)
                return false;
            return objekt.Lookahead == this.Lookahead &&
                    objekt.PozicijaTocke == this.PozicijaTocke &&
                    objekt.RbrProdukcije == this.RbrProdukcije &&
                    objekt.ReprezentSkupa == this.ReprezentSkupa;
        }

        public override int GetHashCode()
        {
            return this.Lookahead.GetHashCode() + this.PozicijaTocke + this.RbrProdukcije;
        }
    }

    public class SkupStavki : HashSet<Stavka>
    {
        private int? hash = null;

        public override int GetHashCode()
        {
            if (hash.HasValue)
                return hash.Value;
            ReHash();
            return hash.Value;
        }

        public override bool Equals(object obj)
        {
            var objekt = obj as SkupStavki;
            if (objekt == null)
                return false;
            if (objekt.Count != this.Count)
                return false;
            foreach (var stavka in this)
                if (!objekt.Contains(stavka))
                    return false;
            return true;
        }

        public new bool Add(Stavka stavka)
        {
            var retVal = base.Add(stavka);
            hash = null;
            return retVal;
        }

        private void ReHash()
        {
            this.hash = 0;
            foreach (var stavka in this)
            {
                this.hash += stavka.GetHashCode();
            }
        }
    }

    //[Serializable]
    //public class Definicija
    //{
    //    public List<Produkcija> Produkcije { get; set; }
    //    public Dictionary<int, Dictionary<string, string>> TablicaAkcija { get; set; }
    //    public Dictionary<int, Dictionary<string, string>> TablicaNovoStanje { get; set; }
    //    public HashSet<string> SinkronizacijskiZnakovi { get; set; }

    //    public Definicija(Generator generator)
    //    {
    //        this.Produkcije = generator.gramatika.Produkcije;
    //        this.TablicaAkcija = generator.tablicaAkcija;
    //        this.TablicaNovoStanje = generator.tablicaNovoStanje;
    //        this.SinkronizacijskiZnakovi = generator.gramatika.SinkronizacijskiZnakovi;
    //    }

    //}

}